/* entity */
import Field from '@model/entity/Field'
import { QualityRuleForm, QualityRuleQualityTime } from '@model/entity/QualityRule'
import ProductCatalog, { ProductCatalogType } from '@model/entity/ProductCatalog'
import { QualityInfoForm, QualityInfoFormGroup } from '@model/entity/QualityInfo'
/* enum */
import { QualityInfoStateEnum, QualityInfoTypeEnum } from '@model/enum/QualityInfoEnum'
import DateFormatEnum from '@model/enum/DateFormatEnum'
import { ProductFieldNameMappingEnum } from '@model/enum/FieldMappingEnum'
/* hooks */
import { useProductCatalogEmpty, useProductCatalogInfoFetch, useProductCatalogInfoFetchParams } from '@hooks/useProductCatalog'
import { useFormComponentUpdatedEmitEvent } from '@hooks/useForm'
/* model */
import { 
  getQualityInfoEndTimeField,
  getQualityInfoStartTimeField,
  QUALITY_INFO_PERIOD_FIELD, 
  QUALITY_INFO_SEPARATOR_FIELD,
  QUALITY_INFO_STATE_FIELD 
} from '@src/component/form/components/FormQualityInfoField/FormQualityInfoModel'
import { getProductCatalogInfoSearchModel } from '@model/param/in/ProductCatalog'
/* props */
import { FormQualityInfoBuildProps } from '@src/component/form/components/FormQualityInfoField/FormQualityInfoBuild/FormQualityInfoBuild.tsx'
import { FormQualityInfoComputedRuleProps } from '@src/component/form/components/FormQualityInfoField/FormQualityInfoBuild/FormQualityInfoComputedRule.tsx'
import { FormQualityInfoComputedRuleAutoProps } from '@src/component/form/components/FormQualityInfoField/FormQualityInfoBuild/FormQualityInfoComputedRuleAuto.tsx'
import { FormQualityInfoComputedRuleManualProps } from '@src/component/form/components/FormQualityInfoField/FormQualityInfoBuild/FormQualityInfoComputedRuleManual.tsx'
/* service */
import { buildQualityInfoForm, isAutoComputedQualityInfo, isManualAddQualityInfo } from '@service/QualityInfoService'
import QualityRuleService from '@service/QualityRuleService'
/* vue */
import { computed, ComputedRef, Ref, ref, watch, nextTick, reactive, onMounted, getCurrentInstance } from 'vue'
import { EmitEvent } from '@model/VC'
/* util */
import moment from 'moment'
import { getFieldIsNull, setFieldIsNull } from '@service/FieldService'
import { cloneDeep } from '@src/util/type'

/** 
 * @see https://dayjs.gitee.io/docs/zh-CN/plugin/is-between
*/

export type QualityInfoValueChangedHandlerType = (value: QualityInfoTypeEnum) => void
export type QualityInfoAutoRuleStartTimeChangedHandlerType = (value: string) => void
export type QualityInfoAutoRuleEndTimeChangedHandlerType = (value: string) => void
export type QualityInfoReturnType = [
  qualityInfoPeriod: Ref<QualityInfoTypeEnum | null>,
  isAutoComputed: ComputedRef<boolean>,
  isManualAdd: ComputedRef<boolean>,
  productCatalog: Ref<ProductCatalogType>,
  setQualityInfoPeriodHandler: (value: QualityInfoTypeEnum) => void,
  qualityInfoAutoFormChangedHandler: (value: QualityInfoForm) => void,
  qualityInfoManualFormChangedHandler: (value: QualityInfoForm) => void,
]
export type QualityInfoComputedRuleAutoReturnType = [
  qualityInfoStartTimeField: ComputedRef<Field>, 
  qualityInfoEndTimeField: ComputedRef<Field>, 
  qualityInfoStateField: ComputedRef<Field>,
  qualityInfoStartTimeChangedHandler: QualityInfoAutoRuleStartTimeChangedHandlerType,
  qualityInfoEndTimeChangedHandler: (value?: string) => void
]
export type QualityInfoComputedRuleManualReturnType = [
  qualityInfoStartTimeField: ComputedRef<Field>, 
  qualityInfoEndTimeField: ComputedRef<Field>, 
  qualityInfoStateField: ComputedRef<Field>,
  qualityInfoStartTimeChangedHandler: QualityInfoAutoRuleStartTimeChangedHandlerType,
  qualityInfoEndTimeChangedHandler: QualityInfoAutoRuleEndTimeChangedHandlerType
]
export type QualityInfoProductCatalogReturnType = [
  isProductCatalogEmpty: ComputedRef<boolean>,
  isQualityRuleTimeFieldDataEmpty: ComputedRef<boolean>
]

export enum useQualityInfoEventEnum {
  Input = 'input'
}

export enum useQualityInfoPeriodEventEnum {
  Input = 'input'
}

export enum useQualityInfoComputedRuleEventEnum {
  Input = 'input'
}

function useQualityInfoSeparatorField(): ComputedRef<Field> {
  // 质保信息 分割线字段
  return computed<Field>(() => QUALITY_INFO_SEPARATOR_FIELD)
}

function useQualityInfoPeriodField(): ComputedRef<Field> {
  // 质保期字段
  return computed<Field>(() => QUALITY_INFO_PERIOD_FIELD)
}

function useQualityInfoStartTimeField(qualityInfoField: Field): ComputedRef<Field> {
  // 质保开始日期字段
  return computed<Field>(() => getQualityInfoStartTimeField(getFieldIsNull(qualityInfoField), qualityInfoField))
}

function useQualityInfoEndTimeField(qualityInfoField: Field): ComputedRef<Field> {
  // 质保结束日期字段
  return computed<Field>(() => getQualityInfoEndTimeField(getFieldIsNull(qualityInfoField), qualityInfoField))
}

function useQualityInfoStateField(): ComputedRef<Field> {
  // 质保状态字段
  return computed<Field>(() => QUALITY_INFO_STATE_FIELD)
}

export function useQualityInfoFormViewGroupFields(field: Field): ComputedRef<Field[]>{
  // 分组字段子字段列表
  return (
    computed<Field[]>(() => {
      return [
        useQualityInfoSeparatorField().value,
        useQualityInfoStartTimeField(field).value,
        useQualityInfoEndTimeField(field).value,
        useQualityInfoStateField().value
      ]
    })
  )
}

export function useQualityInfoTableGroupFields(field: Field): ComputedRef<Field[]>{
  // 分组字段子字段列表
  return (
    computed<Field[]>(() => {
      return [
        useQualityInfoStartTimeField(field).value,
        useQualityInfoEndTimeField(field).value,
        useQualityInfoStateField().value
      ]
    })
  )
}

export function useQualityInfoPeriod(emit: EmitEvent): [ComputedRef<Field>, QualityInfoValueChangedHandlerType] {
  
  // 质保期字段
  const qualityInfoPeriodField = useQualityInfoPeriodField()
  // 质保期数据变化操作方法
  const qualityInfoValueChangedHandler = (value: QualityInfoTypeEnum) => {
    emit(useQualityInfoPeriodEventEnum.Input, value)
  }
  
  return [qualityInfoPeriodField, qualityInfoValueChangedHandler]
}

export function useQualityInfoSeparator(emit: EmitEvent): [ComputedRef<Field>] {
  // 质保信息 分割线字段
  const qualityInfoSeparatorField = useQualityInfoSeparatorField()
  
  return [qualityInfoSeparatorField]
}

export function useQualityInfo(props: FormQualityInfoBuildProps, emit: EmitEvent): QualityInfoReturnType {
  // 产品类型Id
  let productCatalogId: Ref<string> = ref(props?.productCatalogId || '')
  // 产品类型信息
  let productCatalogValue: Ref<{ value: ProductCatalogType }> = ref({ value: {} }) as Ref<{ value: ProductCatalogType }>
  let productCatalog: Ref<ProductCatalogType> = computed(() => productCatalogValue.value.value)
  // 质保期的值
  let qualityInfoPeriod: Ref<QualityInfoTypeEnum | null> = ref(null)
  // 是否为 质保期 自动计算
  const isAutoComputed: ComputedRef<boolean> = computed(() => isAutoComputedQualityInfo(qualityInfoPeriod.value))
  // 是否为 质保期 手动添加
  const isManualAdd: ComputedRef<boolean> = computed(() => isManualAddQualityInfo(qualityInfoPeriod.value))
  
  function getQualityInfoPeriodValue() {
    if (props?.value?.isManualAdd) return QualityInfoTypeEnum.Manual
    
    return QualityInfoTypeEnum.Auto
  }
  
  // 默认值自动计算，编辑的是否仅支持手动添加
  setQualityInfoPeriodHandler(getQualityInfoPeriodValue())
  
  // 更新质保期的值
  function setQualityInfoPeriodHandler(value: QualityInfoTypeEnum) {
    qualityInfoPeriod.value = value
    nextTick(() => {
      useFormComponentUpdatedEmitEvent(emit, props.field as Field, {
        ...props.value,
        isAutoComputed: isAutoComputed.value,
        isManualAdd: isManualAdd.value
      })
    })
  }
  
  // 质保信息计算规则 自动计算 质保开始时间质保结束时间质保状态 数据变化操作
  const qualityInfoAutoFormChangedHandler = (value: QualityInfoForm) => {
    const qualityInfoFormGroupData: QualityInfoFormGroup = {
      ...props.value,
      auto: value
    }
    useFormComponentUpdatedEmitEvent(emit, props.field as Field, qualityInfoFormGroupData)
  }
  // 质保信息计算规则 手动添加 质保开始时间质保结束时间质保状态 数据变化操作
  const qualityInfoManualFormChangedHandler = (value: QualityInfoForm) => {
    const qualityInfoFormGroupData: QualityInfoFormGroup = {
      ...props.value,
      manual: value
    }
    useFormComponentUpdatedEmitEvent(emit, props.field as Field, qualityInfoFormGroupData)
  }

  // 产品类型id变化后更新产品类型的数据
  // @ts-ignore
  watch(
    // @ts-ignore
    () => props.productCatalogId,
    // @ts-ignore
    (newValue: string) => {
      if (newValue === '') return
      
      // 获取产品类型详细信息参数
      const productCatalogParams: ComputedRef<getProductCatalogInfoSearchModel> = useProductCatalogInfoFetchParams(newValue)

      useProductCatalogInfoFetch(productCatalogParams.value).then((result) => {
        productCatalogValue.value.value = result
      })
    },
    { immediate: true }
  )
  
  // @ts-ignore
  watch(
    // @ts-ignore
    () => props?.value?.isManualAdd,
    // @ts-ignore
    (newValue: boolean) => {
      if (newValue && !isManualAdd.value) {
        qualityInfoPeriod.value = QualityInfoTypeEnum.Manual
      }
    }
  )
  return [
    qualityInfoPeriod,
    isAutoComputed,
    isManualAdd,
    productCatalog,
    setQualityInfoPeriodHandler,
    qualityInfoAutoFormChangedHandler,
    qualityInfoManualFormChangedHandler
  ]
}

export function useQualityInfoProductCatalog(productCatalog: Ref<ProductCatalogType>): QualityInfoProductCatalogReturnType {
  // 产品类型数据是否为空
  const isProductCatalogEmpty = useProductCatalogEmpty(productCatalog)
  // 质保信息表单数据
  const qualityInfoForm = useQualityInfoComputedRuleForm(productCatalog)
  // 产品类型 对应的质保时长数据为空
  const isQualityRuleTimeFieldDataEmpty = computed(() => {
    return QualityRuleService.isQualityRuleTimeFieldEmpty(qualityInfoForm.value.qualityTime)
  })
  
  return [isProductCatalogEmpty, isQualityRuleTimeFieldDataEmpty]
}

export function useQualityInfoComputedRule(props: FormQualityInfoComputedRuleProps | FormQualityInfoComputedRuleAutoProps | { productCatalog: Ref<ProductCatalog> }) {
  const qualityRuleForm: ComputedRef<QualityRuleForm> = computed(() => {
    return QualityRuleService.convertQualityRuleRemoteDataToFormQualityRuleFieldValue(props.productCatalog as ProductCatalog)
  })
  
  return [qualityRuleForm]
}

export function useQualityInfoComputedRuleForm(productCatalog: Ref<ProductCatalogType>) {
  return (
    computed(() => {
      return QualityRuleService.convertQualityRuleRemoteDataToFormQualityRuleFieldValue(productCatalog?.value)
    })
  )
}

export function useQualityInfoComputedRuleAuto(props: FormQualityInfoComputedRuleAutoProps, emit: EmitEvent): QualityInfoComputedRuleAutoReturnType {
  // 质保信息 质保开始日期字段
  const qualityInfoStartTimeField = useQualityInfoStartTimeField(props.field as Field)
  // 质保信息 质保结束日期字段
  const qualityInfoEndTimeField = useQualityInfoEndTimeField(props.field as Field)
  // 质保信息 质保状态字段
  const qualityInfoStateField = useQualityInfoStateField()
  // 质保规则表单数据
  const [qualityRuleForm] = useQualityInfoComputedRule(props)

  // 质保开始日期变化后操作
  const qualityInfoStartTimeChangedHandler = (value: string) => {
    const qualityInfoEndTime: string = props.value?.qualityInfoEndTime || ''
    const state: string | QualityInfoStateEnum = useQualityInfoComputedRuleState(value, qualityInfoEndTime)
    emit(
      useQualityInfoComputedRuleEventEnum.Input,
      buildQualityInfoForm(
        value,
        qualityInfoEndTime, 
        state
      )
    )
  }
  // 质保结束日期变化后操作
  const qualityInfoEndTimeChangedHandler = (value?: string) => {
    const qualityInfoStartTime: string = props.value?.qualityInfoStartTime || ''
    let state = ''
    if(value || value === '') {
      state = useQualityInfoComputedRuleState(qualityInfoStartTime, value)
    } else {
      // 结束时间没传值，就走默认的规则~
      const data = useQualityInfoComputedRuleAutoComputedWithStartTime(qualityInfoStartTime, qualityRuleForm)
      value = data[0] || ''
      state = data[1] || ''
    }
    emit(
      useQualityInfoComputedRuleEventEnum.Input, 
      buildQualityInfoForm(qualityInfoStartTime, value, state)
    )
  }
  
  // onMounted(() => {
  //   const qualityInfoStartTime: string = props.value?.qualityInfoStartTime || ''
  //   const qualityInfoEndTime: string = props.value?.qualityInfoEndTime || ''
  //   qualityInfoStartTime && qualityInfoStartTimeChangedHandler(qualityInfoStartTime)
  // })
  
  return [qualityInfoStartTimeField, qualityInfoEndTimeField, qualityInfoStateField, qualityInfoStartTimeChangedHandler, qualityInfoEndTimeChangedHandler]
}

export function useQualityInfoComputedRuleManual(props: FormQualityInfoComputedRuleManualProps, emit: EmitEvent): QualityInfoComputedRuleManualReturnType {
  // 设置质保开始时间字段非必填
  const qualityInfoField: Field | Record<string, any> = cloneDeep(props.field || {})
  setFieldIsNull(qualityInfoField, true)
  // 质保信息 质保开始日期字段
  const qualityInfoStartTimeField = useQualityInfoStartTimeField(qualityInfoField as Field)
  // 质保信息 质保结束日期字段
  const qualityInfoEndTimeField = useQualityInfoEndTimeField(props.field as Field)
  // 质保信息 质保状态字段
  const qualityInfoStateField = useQualityInfoStateField()
  
  // 质保开始日期变化后操作
  const qualityInfoStartTimeChangedHandler = (value: string) => {
    const qualityInfoEndTime: string = props.value?.qualityInfoEndTime || ''
    const state = useQualityInfoComputedRuleState(value, qualityInfoEndTime)
    emit(
      useQualityInfoComputedRuleEventEnum.Input,
      buildQualityInfoForm(
        value,
        qualityInfoEndTime, 
        state
      )
    )
  }
  // 质保结束日期变化后操作
  const qualityInfoEndTimeChangedHandler = (value: string) => {
    const qualityInfoStartTime: string = props.value?.qualityInfoStartTime || ''
    const state = useQualityInfoComputedRuleState(qualityInfoStartTime, value)
    emit(
      useQualityInfoComputedRuleEventEnum.Input, 
      buildQualityInfoForm(qualityInfoStartTime, value, state)
    )
  }
  
  return [qualityInfoStartTimeField, qualityInfoEndTimeField, qualityInfoStateField, qualityInfoStartTimeChangedHandler, qualityInfoEndTimeChangedHandler]
}

export function useQualityInfoComputedRuleManualStartTime() {
  // 
}

export function useQualityInfoComputedRuleAutoComputedWithStartTime(
  startTime: string,
  qualityRuleForm: ComputedRef<QualityRuleForm>
): [string | null, string | null | QualityInfoStateEnum] {
  
  // 质保规则 质保时长 数据
  const qualityRuleTime: QualityRuleQualityTime = qualityRuleForm.value.qualityTime
  if (QualityRuleService.isQualityRuleTimeFieldEmpty(qualityRuleTime)) return [null, null]
  
  let endTime: string
  const timeNumber: number = Number(qualityRuleTime.qualityTimeNumber)
  
  // 没有开始时间
  if (!startTime) {
    endTime = ''
  }
  // 质保规则 质保时长 单位为年
  else if (QualityRuleService.isQualityRuleTimeYear(qualityRuleTime.qualityTimeType)) {
    endTime = moment(startTime).add(timeNumber, 'year').subtract(1, 'day').format(DateFormatEnum.YMD_UP)
  }
  // 质保规则 质保时长 单位为月
  else if (QualityRuleService.isQualityRuleTimeMonth(qualityRuleTime.qualityTimeType)) {
    endTime = moment(startTime).add(timeNumber, 'month').subtract(1, 'day').format(DateFormatEnum.YMD_UP)
  }
  else {
    endTime = ''
  }
  
  const state: string | QualityInfoStateEnum = useQualityInfoComputedRuleState(startTime, endTime)
  
  return [endTime, state]
}

/**
 * @description 获取质保信息计算规则质保状态
 * -- 质保状态分为保内和保外两种，判断规则：
 * ① 如同时存在质保开始日期和质保结束日期，则判断当前日期是否在开始和结束之间，是则为保内，否则为保外
 * ② 如果只添加了质保结束日期，则判断当前日期是否在质保结束日期之前，是则为保内，否则为保外
 * ③ 没有质保结束日期，无法判断质保状态
 * @param {string} startTime
 * @param {string} endTime
 * @return {string | QualityInfoStateEnum}
 */
export function useQualityInfoComputedRuleState(startTime: string, endTime: string): string | QualityInfoStateEnum {
  // 没有质保结束日期，无法判断质保状态
  if (!endTime) return ''
  
  // 如果只添加了质保结束日期，则判断当前日期是否在质保结束日期之前，是则为保内，否则为保外
  if (!startTime) {
    const isBefore: boolean = moment().subtract(1, 'day').isBefore(moment(endTime))
    return isBefore ? QualityInfoStateEnum.In : QualityInfoStateEnum.Out
  }
  
  const today = moment().format(DateFormatEnum.YMD_UP)
  // 第四个参数是设置包容性。 [ 表示包含。 ( 表示排除
  const isBetweenTime: boolean = moment(today).isBetween(startTime, endTime, null, '[]')
  return isBetweenTime ? QualityInfoStateEnum.In : QualityInfoStateEnum.Out
}
